﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Brain.Editor;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Brain.IO;

namespace Brain
{
    /// <summary>
    /// Manages Content for the Engine
    /// </summary>
    public class DefaultContentManager : IContentManager
    {
        public void DeserializedAll()
        {
        }
        public ContentManager ContentManager { get; set; }
        public ContentManager ConFileManager;

        protected List<IDisposable> Content;

        /// <summary>
        /// Public Constructor for the Default Content Manager
        /// </summary>
        public DefaultContentManager()
        {
            ContentManager = new ContentManager(Engine.Instance.ServiceProvider);
            ConFileManager = new ContentManager(Engine.Instance.ServiceProvider, "C:/");
            ContentManager.RootDirectory = "Content";

            Content = new List<IDisposable>();
        }

        public void AssignOwnership(IDisposable disp)
        {
            this.Content.Add(disp);
        }

        public Texture2D Load(TextureLoader loader)
        {
            if (loader.Places.Length != loader.Resolutions.Length)
            {
                throw new Exception("Number of TexturePlaces differ from the number of Resolutions!");
            }

            Resolution current = Resolution.CurrentResolution;

            int chose = -1;
            int closenessWidth = int.MaxValue;
            int closenessHeight = int.MaxValue;
            for (int i = 0; i < loader.Places.Length; i++)
            {
                Resolution res = loader.Resolutions[i];

                int cloWidth = Math.Abs(res.Width - current.Width);
                int cloHeight = Math.Abs(res.Height - current.Height);
                if (cloWidth + cloHeight < closenessWidth + closenessHeight)
                {
                    closenessHeight = cloHeight;
                    closenessWidth = cloWidth;
                    chose = i;
                }
            }

            return Load<Texture2D>(loader.Places[chose]);
        }

        /// <summary>
        /// Loads a file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="place"></param>
        /// <returns></returns>
        public T Load<T>(string place)
        {
            string lower = place.ToLower();

            if (lower.StartsWith("confile:"))
            {
                if (Engine.Instance.SerializationManager != null &&
                    Engine.Instance.SerializationManager.SceneData != null)
                {
                    string[] splitted = place.Split(':');
                    string name = splitted[1];

                    EditorSceneData data = Engine.Instance.SerializationManager.SceneData;
                    SceneContent project = data.ContentProject;
                    for (int k = 0; k < project.Files.Count; k++)
                    {
                        SceneContentFile file = project.Files[k];
                        if (file.LoadedData != null)
                        {
                            return (T)file.LoadedData;
                        }
                        if (file.Name == name)
                        {
                            string path = file.ProcessedPath;

                            object o = CheckCustomFormats<T>(path);
                            if (o != null)
                            {
                                file.LoadedData = o;
                                return (T)o;
                            }
                            T t = ConFileManager.Load<T>(path);;
                            file.LoadedData = t;

                            return t;
                        }
                    }
                }
            }
            else
            {
                object o = CheckCustomFormats<T>(place);
                if (o != null)
                {
                    return (T)o;
                }
                if (place == "null")
                {
                    return default(T);
                }
                
                return ContentManager.Load<T>(place);
            }

            return default(T);
        }

        public T CheckCustomFormats<T>(string place)
        {
            Type typeT = typeof(T);
            if (typeT == typeof(BrainModel))
            {
                using (FileStream stream = new FileStream(place, FileMode.Open))
                {
                    //BrainModel model = BrainModel.Read(stream);
                    //return (T)((object)model);
                    return default(T);
                }
            }
            else if (typeT == typeof(HeightMap))
            {
                using (FileStream stream = new FileStream(place, FileMode.Open))
                {
                    TerrainFile file = new TerrainFile();
                    file.Deserialize(stream);
                    return (T)((object)file.MakeHeightMap());
                }
            }

            return default(T);
        }


        public virtual void Reset()
        {
            for (int i = 0; i < Content.Count; i++)
            {
                IDisposable disp = Content[i];
                disp.Dispose();
            }
            Content.Clear();
            Content.Capacity = 0;

            this.ContentManager.Dispose();

            this.ContentManager = new ContentManager(Engine.Instance.ServiceProvider);
            ContentManager.RootDirectory = "Content";
        }

        public virtual void Dispose()
        {
            for (int i = 0; i < Content.Count; i++)
            {
                IDisposable disp = Content[i];
                disp.Dispose();
            }
            Content.Clear();
            Content.Capacity = 0;

            this.ContentManager.Dispose();
            this.ContentManager = null;
        }

        public SerializationData Data { get; set; }

        public void SerializeData(DefaultSerializationManager manager)
        {
        }

        public void DeserializeData(DefaultSerializationManager manager, SerializationData newData)
        {
        }






        
    }
}
